網頁在運行的時候,難免會拋出錯誤。當我們沒有做任何錯誤處理時,網頁有任何錯誤拋出就會卡住不動,最慘的狀況就是網頁一片空白,使用者也不知道發生什麼事。
這時我們就需要捕捉網頁中的錯誤,並且根據錯誤回饋給使用者一個錯誤頁面。最好要有一個「重新整理」的按鈕,讓使用者可以不用真的按下 F5
來重整網頁,畢竟按下 F5
重新整理 js 的暫存記憶體都會清空,畫面也要重新請求,這樣 cost 會比較大。
接下來會講到 Next 如何實作錯誤處理以及背後的實作方式。
app
router 裡可以建立 error
component,這時 Next 會自動建立一個 error boundary 來捕捉 page
component 拋出的任何 error,如果捕捉到錯誤就會顯示 error
的 UI。
error
component'use client' // error 一定要是 client component
import { useEffect } from 'react'
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
useEffect(() => {
// log 錯誤訊息
console.error(error)
}, [error])
return (
<div>
<h2>Something went wrong!</h2>
<button
onClick={
// 重新整理
() => reset()
}
>
Try again
</button>
</div>
)
}
在同一個 folder 中建立的 error
只會包住 page
,只有 page
拋出錯誤時才會捕捉到。其他像是 layout
、template
這些共用 UI 並不會包含進去,原因是路由切換時這些共用 UI 不太會發生錯誤。
每個 folder 都可以建立自己的 error
handling,當路由嵌套時就會有多個 error
互相嵌套。
若 child page
拋出錯誤時,它會優先被離他最近的 child folder 建立的 error
所捕捉,這也很好理解,畢竟近水樓臺先得月。
底下 /dashboard 這個 route 拋出的錯誤會優先被 dashboard 這個資料夾的 error
所捕捉,若 dashboard 沒有建立 error
,才會往上被根目錄的 error
捕捉。
error
必須是 client component。error
的 props 可以解構出兩個參數:error 和 reset。props 解構出來的 error 就是子組件拋出的錯誤資訊,可以根據錯誤內容顯示不同的 UI。
reset 則是一個 function,執行後會重新 re-render page
component,而不需要重新整理網頁。
上面講到 error
並不會捕捉到同一層 layout
或 template
的錯誤,如果需要捕捉共用組件的 UI,就必須在更上一層建立一個 error 來捕捉子層共用 UI 拋出的錯誤。
這樣一直追上去就會發生一個問題,就是沒辦法幫根目錄的 layout 與 template 建立 error handling。
這就是 global-error
誕生的其中一個目的,global-error
包住了整個 web app,也是整個 web app 的最後一道防線,這裡沒捕捉到錯誤那網頁就等著卡住了。
與一般 error
的寫法不同,有幾個需要注意的地方:
global-error
這個檔案global-error
必須定義 <html>
與 <body>
這樣我們就可以為整個 web app 加上最後一道保障。
global-error
component<html>
與 <body>
的 client component'use client'
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}
Next 使用的 Error Handling 就是 React 本身常見的 error boundary 的作法。
它是使用 react class component 的寫法,捕捉 children
拋出的錯誤,並且返回 fallback
props 的 UI。
有興趣的人可以看看 React 官網的文章
寫鐵人賽的同時邊 loop 這首 guitar solo,jam 的超好聽 OwO
他還在 2022 年用同一個 beats 再 jam 了一次,也超級好聽,建議晚上不要聽,不然會 loop 到天亮。